
package com.dqx.utils;

import android.graphics.SurfaceTexture;
import android.hardware.Camera;

import java.io.IOException;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * 摄像头工具类
 */
public class CameraUtils implements ICamera {
    //配置
    private Config mConfig;
    //相机
    private Camera mCamera;
    //图片大小
    private Camera.Size picSize;
    //预览大小
    private Camera.Size preSize;

    private CameraSizeComparator sizeComparator;

    private Camera.CameraInfo mCameraInfo;

    public CameraUtils() {
        sizeComparator = new CameraSizeComparator();

        //默认设置
        this.mConfig = new Config();
        mConfig.previewWidth = 720;
        mConfig.pictureWidth = 720;
        mConfig.rate = 1.778f;
    }

    /**
     * 打开相机
     *
     * @param cameraId
     * @return
     */
    @Override
    public boolean open(int cameraId) {
        mCamera = Camera.open(cameraId);

        if (mCamera != null) {
            Camera.Parameters param = mCamera.getParameters();
            picSize = getPropPictureSize(param.getSupportedPictureSizes(), mConfig.rate,
                    mConfig.pictureWidth);
            preSize = getPropPreviewSize(param.getSupportedPreviewSizes(), mConfig.rate, mConfig
                    .previewWidth);
            param.setPictureSize(picSize.width, picSize.height);
            param.setPreviewSize(preSize.width, preSize.height);
            //打开前置摄像头
            Camera.CameraInfo info = new Camera.CameraInfo();
            Camera.getCameraInfo(cameraId, info);
            mCameraInfo = info;
            int cameraFacing = info.facing;
            if (cameraFacing == Camera.CameraInfo.CAMERA_FACING_BACK) {//后置摄像头
                param.setFocusMode(param.FOCUS_MODE_AUTO);
            }
            mCamera.setParameters(param);
        }
        mCamera.autoFocus(null);
        mCamera.cancelAutoFocus();
        return false;
    }

    /**
     * 设置预览处理控件
     *
     * @param texture
     */
    public void setPreviewTexture(SurfaceTexture texture) {
        if (mCamera != null) {
            try {
                mCamera.setPreviewTexture(texture);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 设置配置
     *
     * @param config
     */
    @Override
    public void setConfig(Config config) {
        this.mConfig = config;
    }

    /**
     * 开始预览
     *
     * @return
     */
    @Override
    public boolean preview() {
        if (mCamera != null)
            mCamera.startPreview();
        return false;
    }

    /**
     * 切换相机
     *
     * @param cameraId
     * @return
     */
    @Override
    public boolean switchTo(int cameraId) {
        close();
        open(cameraId);
        return false;
    }

    /**
     * 拍照
     *
     * @param callback
     */
    @Override
    public void takePhoto(TakePhotoCallback callback) {

    }

    /**
     * 获取摄像方向
     *
     * @return
     */
    public int getOrientation() {
        if (mCameraInfo != null) {
            return mCameraInfo.orientation;
        }
        return 0;
    }

    /**
     * 关闭相机
     *
     * @return
     */
    @Override
    public boolean close() {
        if (mCamera != null) {
            try {
                mCamera.stopPreview();
                mCamera.release();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return false;
    }

    /**
     * 设置预览回调
     *
     * @param callback
     */
    @Override
    public void setOnPreviewFrameCallback(final PreviewFrameCallback callback) {
        if (mCamera != null)
            mCamera.setPreviewCallback(new Camera.PreviewCallback() {
                @Override
                public void onPreviewFrame(byte[] data, Camera camera) {
                    callback.onPreviewFrame(data, preSize.width, preSize.height);
                }
            });
    }

    /**
     * 设置预览回调
     *
     * @param callback
     */
    public void setOnPreviewFrameCallbackWithBuffer(final PreviewFrameCallback callback) {
        if (mCamera != null)
            mCamera.setPreviewCallbackWithBuffer(new Camera.PreviewCallback() {
                @Override
                public void onPreviewFrame(byte[] data, Camera camera) {
                    callback.onPreviewFrame(data, preSize.width, preSize.height);
                }
            });
    }

    /**
     * 获取预览大小
     *
     * @return
     */
    @Override
    public Camera.Size getPreviewSize() {
        return preSize;
    }

    /**
     * 获取图片大小
     *
     * @return
     */
    @Override
    public Camera.Size getPictureSize() {
        return picSize;
    }


    /**
     * 获取合适的预览大小
     *
     * @param list
     * @param th
     * @param minWidth
     * @return
     */
    private Camera.Size getPropPreviewSize(List<Camera.Size> list, float th, int minWidth) {
        Collections.sort(list, sizeComparator);

        int i = 0;
        for (Camera.Size s : list) {
            if ((s.height >= minWidth) && equalRate(s, th)) {
                break;
            }
            i++;
        }
        if (i == list.size()) {
            i = 0;
        }
        return list.get(i);
    }

    /**
     * 获取合适的图片大小
     *
     * @param list     摄像头支持的图片大小集合
     * @param th       宽高比
     * @param minWidth
     * @return
     */
    private Camera.Size getPropPictureSize(List<Camera.Size> list, float th, int minWidth) {
        //排序
        Collections.sort(list, sizeComparator);

        int i = 0;
        for (Camera.Size s : list) {
            if ((s.height >= minWidth) && equalRate(s, th)) {
                break;
            }
            i++;
        }
        if (i == list.size()) {
            i = 0;
        }
        return list.get(i);
    }

    /**
     * 比较宽高比
     *
     * @param s
     * @param rate
     * @return
     */
    private boolean equalRate(Camera.Size s, float rate) {
        float r = (float) (s.width) / (float) (s.height);
        if (Math.abs(r - rate) <= 0.03) {//接近
            return true;
        } else {
            return false;
        }
    }

    /**
     * 比较器
     */
    private class CameraSizeComparator implements Comparator<Camera.Size> {
        public int compare(Camera.Size lhs, Camera.Size rhs) {
            if (lhs.height == rhs.height) {
                return 0;
            } else if (lhs.height > rhs.height) {
                return 1;
            } else {
                return -1;
            }
        }

    }

}
